// Copyright (C) 2010 Razvan Constantin <razvan.constantin@rconst.net>
//
// This file is part of FileBow.
//
// FileBow is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// FileBow is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FileBow.  If not, see <http://www.gnu.org/licenses/>.
//
// Declaration of FileFilter.

#ifndef LOGIC_FILE_FILTER_H_
#define LOGIC_FILE_FILTER_H_

#include <string>
#include <vector>

#include "common/common.h"
#include "logic/path-tree.h"

namespace filebow {

/**
 * Result for filtering.
 */
enum FilterResult {
  DONT_CARE,
  INCLUDE,
  EXCLUDE,
};

FilterResult CombineFilterResult(FilterResult l, FilterResult r);

/**
 * File filter interface.
 */
class FileFilter {

  // Constructor.
  public: FileFilter();

  // Virtual destructor.
  public: virtual ~FileFilter();

  // Creates a statefull filter for the given node (usually directory).
  // @return a new filter with state set for the given node or NULL
  //   if filter doesn't support/require partial filtering with state.
  //   Caller takes ownership of returned object.
  public: virtual FileFilter* FilterPartial(const PathTree::Node& node) const;

  // Indicates whether the given node should be included or excluded.
  // May return NONE when filtering result is undecided.
  public: virtual FilterResult Filter(const PathTree::Node& node) const;

  DISALLOW_COPY(FileFilter);
};

/**
 * A filter which allows combining multiple filters with a single
 * interface.
 */
class CompositeFilter : public FileFilter {

  // Constructor.
  public: CompositeFilter();
  // Destructor.
  public: ~CompositeFilter();

  // Appends and takes ownership of the given filter.
  public: void AddFilter(FileFilter* filter);

  // @Override.
  public: FileFilter* FilterPartial(const PathTree::Node& node) const;
  // @Override.
  public: FilterResult Filter(const PathTree::Node& node) const;

  // Inner filters. Owned.
  private: std::vector<FileFilter*> mFilters;
};

/**
 * A filter which return always the given result.
 */
class ConstFilter : public FileFilter {

  // Constructor.
  public: ConstFilter(FilterResult result);
  // Destructor.
  public: ~ConstFilter();

  // @Override.
  public: FilterResult Filter(const PathTree::Node& node) const;

  // Const result.
  private: FilterResult mResult;
};

/**
 * Match filter.
 */
class MatchFilter : public FileFilter {

  // Constructor.
  public: MatchFilter();
  // Destructor.
  public: ~MatchFilter();

  // Fragments to match. Ownership stays with filter.
  public: std::vector<std::string>* fragments() { return &mFragments; }

  // @Override.
  public: FileFilter* FilterPartial(const PathTree::Node& node) const;
  // @Override.
  public: FilterResult Filter(const PathTree::Node& node) const;

  // Fragments to match.
  private: std::vector<std::string> mFragments;
};

/**
 * Exclude filter.
 */
class ExcludeFilter : public FileFilter {

  // Constructor.
  public: ExcludeFilter();
  // Destructor.
  public: ~ExcludeFilter();

  // Fragments to match for exclusion. Ownership stays with filter.
  public: std::vector<std::string>* fragments() { return &mFragments; }

  // @Override.
  public: FilterResult Filter(const PathTree::Node& node) const;

  // Fragments to match for exclusions.
  private: std::vector<std::string> mFragments;
};

FileFilter* EnsurePartialFilter(const FileFilter& filter,
                                const PathTree::Node& node);

FileFilter* ParseFilter(const std::string& filterStr);

}  // namespace filebow

#endif  // LOGIC_FILE_FILTER_H_
